package ca

import (
	"bufio"
	"bytes"
	"encoding/json"
	"errors"
	"fmt"
	"github.com/cihub/seelog"
	"io"
	"myFtp/conf"
	"myFtp/influxdb"
	"myFtp/util"
	"net/http"
	"strconv"
	"strings"
	"time"
)

func nec1010(destPath string, data []byte) int64 {
	lastIndex := strings.LastIndex(destPath, "/")
	if lastIndex < 0 {
		lastIndex = 0
	}
	fileName := destPath[lastIndex:]
	if fileName != "" {
		fileNames := strings.Split(fileName, "_")
		if len(fileNames) > 2 {
			deviceId := fileNames[1]
			//fmt.Println("=======", deviceId)
			var allDeviceFlow []*influxdb.DeviceFlow
			bo := bufio.NewReader(bytes.NewReader(data))
			for {
				line, _, err := bo.ReadLine()
				if err == io.EOF {
					break
				}
				df, err := str2DeviceFlow(deviceId, string(line))
				if err != nil {
					seelog.Error(err)
					return 0
				}
				allDeviceFlow = append(allDeviceFlow, df)
			}
			//json,_:=json.Marshal(allDeviceFlow)
			//seelog.Error(fmt.Sprintf("=== %s", json))
			//发送 并插入 influxdb
			filterData(destPath, allDeviceFlow)
			return int64(bo.Size())
		} else {
			seelog.Errorf("file name is not standardized %v", destPath)
			return 0
		}
	} else {
		seelog.Errorf("file name is not standardized %v", destPath)
		return 0
	}
}

func str2DeviceFlow(deviceId, str string) (*influxdb.DeviceFlow, error) {
	idLen := len(deviceId)
	if !strings.Contains(str, "1g") {
		return nil, errors.New(fmt.Sprintf("this line has error %v", str))
	}
	if str[:idLen] == deviceId {
		index1g := strings.Index(str, "1g")
		year, err := strconv.Atoi(str[index1g-12 : index1g-8])
		if err != nil {
			return nil, err
		}

		month, err := strconv.Atoi(str[index1g-8 : index1g-6])
		if err != nil {
			return nil, err
		}

		day, err := strconv.Atoi(str[index1g-6 : index1g-4])
		if err != nil {
			return nil, err
		}

		hour, err := strconv.Atoi(str[index1g-4 : index1g-2])
		if err != nil {
			return nil, err
		}

		min, err := strconv.Atoi(str[index1g-2 : index1g])
		if err != nil {
			return nil, err
		}
		t := time.Date(year, time.Month(month), day, hour, min, 0, 0, time.Local)
		enter0, err := strconv.Atoi(str[index1g+2 : index1g+6])
		if err != nil {
			return nil, err
		}
		exit0, err := strconv.Atoi(str[index1g+6 : index1g+10])
		if err != nil {
			return nil, err
		}
		df := influxdb.DeviceFlow{
			DeviceId:   deviceId,
			ZoneId:     "0",
			Time:       t,
			CountEnter: enter0,
			CountExit:  exit0,
		}
		return &df, nil
	} else {
		return nil, errors.New("文件名称deviceId和文件内容不匹配")
	}

}

func filterData(destPath string, allDeviceFlow []*influxdb.DeviceFlow) {
	//查询数据库有没有这个数据，如果 没有或者 有并且 status = 0 则发送，status= 1 则不发送
	if len(allDeviceFlow) > 0 {
		startTime := allDeviceFlow[0].Time.Format(util.DateTimeFormat)
		endTime := allDeviceFlow[len(allDeviceFlow)-1].Time.Format(util.DateTimeFormat)
		deviceId := allDeviceFlow[0].DeviceId
		findDeviceFlow := conf.InfluxdbConnect().SelectDeviceFlowByDeviceIdAndTime(influxdb.Allflow, deviceId, startTime, endTime)

		fdfMap := make(map[string]*influxdb.DeviceFlow, len(findDeviceFlow))
		for _, val := range findDeviceFlow {
			fdfMap[fmt.Sprintf("%v_%v_%v", val.DeviceId, val.ZoneId, val.Time)] = val
		}
		newDF := new([]*influxdb.DeviceFlow)
		for _, val := range allDeviceFlow {
			if fdfMap[fmt.Sprintf("%v_%v_%v", val.DeviceId, val.ZoneId, val.Time)] == nil {
				*newDF = append(*newDF, val)
			}
		}
		seelog.Infof("== new DeviceFlow len: %v", len(*newDF))
		bo := SendAndSave(*newDF)
		saveDestPath(destPath, bo)
	} else {
		seelog.Errorf("Error file: %v not analysis . size %v", destPath, len(allDeviceFlow))
	}

}

func saveDestPath(destPath string, status bool) {
	fileStatus := -1
	if status {
		fileStatus = 0
	}
	des := strings.Split(strings.Replace(destPath, ".txt", "", -1), "_")
	fileTag := fmt.Sprintf("%v", des[1])
	seelog.Infof("==============tag %v\n", des[1])
	files := []*influxdb.FtpFile{
		&influxdb.FtpFile{
			Time:     time.Now(),
			FileTag:  fileTag,
			FileName: destPath,
			Status:   fileStatus,
		},
	}
	conf.InfluxdbConnect().GroupInsertFtpFile(files, influxdb.FTPFILE)
}

func ExectNotSuccess() {
	df := conf.InfluxdbConnect().SelectDeviceFlowByStatus(influxdb.Allflow, 0)
	SendAndSave(df)
	seelog.Errorf("exect not success size:%v content:%v", len(df), df)
}

func SendAndSave(allDeviceFlow []*influxdb.DeviceFlow) bool {

	sendModel := make(map[string]*influxdb.SendModel)
	for _, val := range allDeviceFlow {
		timeStr := val.Time.Format(util.DateTimeFormat)
		inout := influxdb.InOut{
			ZoneId:        val.ZoneId,
			StartDateTime: timeStr,
			EndDateTime:   timeStr,
			In:            val.CountEnter,
			Out:           val.CountExit,
			Time:          val.Time,
		}
		if sendModel[val.DeviceId] == nil {
			sendModel[val.DeviceId] = &influxdb.SendModel{
				DeviceId: val.DeviceId,
			}
		}
		sendModel[val.DeviceId].InOutMetrics = append(sendModel[val.DeviceId].InOutMetrics, inout)
	}

	insertLen := 0

	for _, val := range sendModel {
		status := false
		if data, err := json.Marshal(val); err == nil {
			if b := httpClient(data); b {
				status = true
			}
		}
		if status { //true
			le := conf.InfluxdbConnect().InsertDeviceFlowBySendModel(val, 1)
			insertLen += le
			seelog.Errorf("tag==1 %v save  len:%v", val.DeviceId, le)
		} else {
			le := conf.InfluxdbConnect().InsertDeviceFlowBySendModel(val, 0)
			insertLen += le
			seelog.Errorf("tag==0 %v save  len:%v %+v", val.DeviceId, le, val)
		}
	}
	if len(allDeviceFlow) == 0 {
		return true
	} else {
		return len(allDeviceFlow) == insertLen
	}

}

func httpClient(data []byte) bool {
	client := &http.Client{}
	req, err := http.NewRequest("POST",
		conf.GetSenUrl(),
		strings.NewReader(string(data)))
	req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
	if err != nil {
		panic(err)
	}
	if resp, err := client.Do(req); err == nil {
		code := resp.StatusCode
		seelog.Errorf("send %v code :%v ", conf.GetSenUrl(), code)
		if code == 200 {
			return true
		}
	} else {
		seelog.Error(err)
	}
	return false

}
